/*
     Copyright 2007 Joseph M. Ferner

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System.Net;
using System.Net.Sockets;
using System.Text;
using OpenServers.Net.Common.FileSystem;
using OpenServers.Net.Common.Listener;
using OpenServers.Net.Common.Socket;
using OpenServers.Net.Common.State;
using OpenServers.Net.Common.User;
using OpenServers.Net.FtpServer.Command;

namespace OpenServers.Net.FtpServer.State {
    /// <summary>
    /// State object to store FTP connection related data.
    /// </summary>
    public class FtpState : AbstractState {
        /// <summary>
        /// The current output type. (Ascii, Image, etc.).
        /// </summary>
        public class Type {
            /// <summary>
            /// The type.
            /// </summary>
            public enum TypeEnum {
                /// <summary>
                /// Byte for byte no modification.
                /// </summary>
                Image,

                /// <summary>
                /// Ensure all bytes are ascii.
                /// </summary>
                Ascii,

                /// <summary>
                /// Ebcdic, are you kidding me who uses this?
                /// </summary>
                Ebcdic,

                /// <summary>
                /// Specifies the byte size.
                /// </summary>
                LocalByteSize
            }

            /// <summary>
            /// Subtype.
            /// </summary>
            public enum SubTypeEnum {
                /// <summary>
                /// Not sure?
                /// </summary>
                NonPrint,

                /// <summary>
                /// Not sure?
                /// </summary>
                TelnetFormEffectors,

                /// <summary>
                /// Not sure?
                /// </summary>
                CarriageControl
            }

            private TypeEnum _currentType;
            private SubTypeEnum _subType;
            private int _localByteSize;

            /// <summary>
            /// constructor. Sets the type to ASCII and the subtype to Nonprint.
            /// </summary>
            public Type() {
                _currentType = TypeEnum.Ascii;
                _subType = SubTypeEnum.NonPrint;
            }

            /// <summary>
            /// Gets/Sets the current type.
            /// </summary>
            public TypeEnum CurrentType {
                get { return _currentType; }
                set {
                    _currentType = value;
                    _subType = SubTypeEnum.NonPrint;
                }
            }

            /// <summary>
            /// Gets/Sets the subtype.
            /// </summary>
            public SubTypeEnum SubType {
                get { return _subType; }
                set { _subType = value; }
            }

            /// <summary>
            /// Gets/Sets the local byte size.
            /// </summary>
            public int LocalByteSize {
                get { return _localByteSize; }
                set { _localByteSize = value; }
            }
        }

        private readonly StringBuilder _commandBuffer = new StringBuilder();
        private string _userName;
        private IUser _user;
        private IPAddress _lastPortCommandIpAddress;
        private int? _lastPortCommandPort;
        private string _currentDirectory = "/";
        private bool _isPassive = false;
        private IFileSystemObject _lastRenameFrom;
        private Type _type = new Type();
        private string _lastRestart;

        /// <summary>
        /// constructor.
        /// </summary>
        public FtpState(IListener listener, ISocket clientSocket)
            : base(listener, clientSocket) {
        }

        /// <summary>
        /// Command buffer to que up characters until a new line is reached.
        /// </summary>
        public StringBuilder CommandBuffer {
            get { return _commandBuffer; }
        }

        /// <summary>
        /// The current user name. This stores the user name before the password command is issued.
        /// </summary>
        public string UserName {
            get { return _userName; }
            set { _userName = value; }
        }

        /// <summary>
        /// The validated user.
        /// </summary>
        public IUser User {
            get { return _user; }
            set { _user = value; }
        }

        /// <summary>
        /// Last PORT command ip address <see cref="PortCommand"/>.
        /// </summary>
        public IPAddress LastPortCommandIpAddress {
            get { return _lastPortCommandIpAddress; }
            set { _lastPortCommandIpAddress = value; }
        }

        /// <summary>
        /// Last PORT command port <see cref="PortCommand"/>.
        /// </summary>
        public int? LastPortCommandPort {
            get { return _lastPortCommandPort; }
            set { _lastPortCommandPort = value; }
        }

        /// <summary>
        /// The current directory relative to the root of the file system.
        /// </summary>
        public string CurrentDirectory {
            get { return _currentDirectory; }
            set { _currentDirectory = value; }
        }

        /// <summary>
        /// Is passivate mode.
        /// </summary>
        public bool IsPassive {
            get { return _isPassive; }
            set { _isPassive = value; }
        }

        /// <summary>
        /// Last rename from command <see cref="RenameFromCommand"/>.
        /// </summary>
        public IFileSystemObject LastRenameFrom {
            get { return _lastRenameFrom; }
            set { _lastRenameFrom = value; }
        }

        /// <summary>
        /// The currently set type <see cref="TypeCommand"/>.
        /// </summary>
        public Type CurrentType {
            get { return _type; }
            set { _type = value; }
        }

        /// <summary>
        /// The last restart string <see cref="RestartCommand"/>.
        /// </summary>
        public string LastRestart {
            get { return _lastRestart; }
            set { _lastRestart = value; }
        }
    }
}
